
package com.xtsoft.platform.base.system.service.impl;


import com.xtsoft.core.service.impl.GenericServiceImpl;
import com.xtsoft.core.utils.BeanUtil;
import com.xtsoft.core.utils.ResultMsg;
import com.xtsoft.core.utils.tree.CommonTreeNode;
import com.xtsoft.core.utils.tree.TreeBuilder;
import com.xtsoft.platform.base.system.domain.*;
import com.xtsoft.platform.base.system.repository.*;
import com.xtsoft.platform.base.system.service.SysResourceService;
import com.xtsoft.platform.globe.Constants.Constants;
import com.xtsoft.platform.globe.enums.ResourceType;
import com.xtsoft.platform.globe.enums.YesNo;
import com.xtsoft.platform.globe.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


@Service("sysResourceService")
public class SysResourceServiceImpl extends GenericServiceImpl<SysResource, String, SysResourceRepository>
		implements SysResourceService {

	@Autowired
	private SysResourceRepository sysResourceRepository;
	@Autowired
	private UserRoleRepository userRoleRepository;
	@Autowired
	private ResourceRoleRepository resourceRoleRepository;
	@Autowired
	private SysRoleRepository sysRoleRepository;
	@Autowired
	private SysUserRepository sysUserRepository;
	/**
	 * 构建当前用户资源菜单树
	 * 
	 * @throws IntrospectionException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public List<CommonTreeNode> getResourceTree(SysUser sysUser) throws NoSuchFieldException, SecurityException,
			IllegalArgumentException, IllegalAccessException, InvocationTargetException, IntrospectionException {
		List<UserRole> userRoles = userRoleRepository.findBySysUser(sysUser);
		if (null == userRoles || userRoles.size() < 1) {
			return null;
		}
		List<SysRole> sysRoles = userRoles.stream().map(mapper -> mapper.getSysRole()).distinct()
				.collect(Collectors.toList());
		List<ResourceRole> resourceRoles = resourceRoleRepository.findBySysRoleIn(sysRoles);
		if (null == resourceRoles || resourceRoles.size() < 1) {
			return null;
		}

		List<SysResource> resources = resourceRoles.stream()
				.filter(predicate -> predicate.getSysResource().getResourceType() == ResourceType.Menu.getIntValue())
				.map(mapper -> mapper.getSysResource()).distinct().collect(Collectors.toList());

		// 排序，无法用数据库排序，若能用数据库排序，则应该用数据库排序提升性能
		Collections.sort(resources, new Comparator<SysResource>() {
			@Override
			public int compare(SysResource o1, SysResource o2) {
				return o1.getSerialNo().compareTo(o2.getSerialNo());
			}

		});

		// 通用树构建示例--Start
		// 1) 做个根节点
		/*
		 * SysResource rootNode = new SysResource();
		 * rootNode.setResourceId(Constants.RootNode);
		 * rootNode.setResUniqueId(Constants.RootNode);
		 * rootNode.setResourceName("菜单列表"); rootNode.setIconClsId("");
		 * rootNode.setSerialNo(1); resources.add(rootNode);
		 */
		// 构建树节点，当提供了排序属性，则构造排序树
		TreeBuilder<SysResource> treeBuilder = new TreeBuilder();
		List<CommonTreeNode> menuList = treeBuilder.build(resources, "resUniqueId", "resourceId", "preResourceId",
				"resourceName", "iconClsId", "serialNo", "attachMethod");
		return menuList;
	}


	/**
	 * 构建资源复选框树
	 * 
	 * @throws IntrospectionException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	@Override
	public List<CommonTreeNode> getResourceCheckTree(boolean needRootNode) throws NoSuchFieldException, SecurityException,
			IllegalArgumentException, IllegalAccessException, InvocationTargetException, IntrospectionException {
	
		SysUser user=(SysUser) SecurityUtils.getLoginedUser();
		List<UserRole> userRoles = userRoleRepository.findBySysUser(user);
		List<SysRole> sysRoles = new ArrayList<SysRole>();
		userRoles.forEach(action->{sysRoles.add(sysRoleRepository.findById(action.getSysRole().getRoleId()).get());});
		List<ResourceRole> resourceRoles = new ArrayList<>();
		sysRoles.forEach(action->resourceRoles.addAll(resourceRoleRepository.findBySysRole(action)));
		List<String> ids = new ArrayList<>();
		resourceRoles.forEach(action->ids.add(action.getSysResource().getResUniqueId()));
		List<SysResource> sysResources = sysResourceRepository.findByResUniqueIdIn(ids);
		List<SysResource> list = sysResources.stream().map(mapper->mapper).distinct().filter(predicate->predicate.getResourceType().equals(ResourceType.Menu.getIntValue())).collect(Collectors.toList());
		//list.addAll(sysResources.stream().map(mapper->mapper).distinct().filter(predicate->predicate.getResourceType().equals(ResourceType.Other.getIntValue())).collect(Collectors.toList()));
		//list.addAll(sysResources.stream().map(mapper->mapper).distinct().filter(predicate->predicate.getResourceType().equals(ResourceType.ViewMenu.getIntValue())).collect(Collectors.toList()));
		List<Integer> typeList = new ArrayList<Integer>();
		typeList.add(ResourceType.Menu.getIntValue());
		//typeList.add(ResourceType.Other.getIntValue());
		//typeList.add(ResourceType.ViewMenu.getIntValue());
		List<SysResource> treelist = sysResourceRepository
				.findByResourceTypeInAndStateOrderBySerialNoAsc(typeList, YesNo.Yes.getIntValue());
		if(needRootNode) {
			SysResource rootNode = new SysResource();
			rootNode.setResourceId(Constants.RootNode);
			rootNode.setResUniqueId(Constants.RootNode);
			rootNode.setResourceName("菜单列表");
			rootNode.setIconClsId("x-fa fa-th-list");
			rootNode.setSerialNo(1);
			list.add(rootNode);
		}
		// 构建树节点，当提供了排序属性，则构造排序树
		TreeBuilder<SysResource> treeBuilder = new TreeBuilder();
		List<CommonTreeNode> menuList = treeBuilder.buildWithChecked(treelist, list, "resUniqueId", "resourceId",
				"preResourceId", "resourceName", "iconClsId", "serialNo", "attachMethod");
		return menuList;
	}

	/**
	 * 构建所有资源树
	 * 
	 * @throws IntrospectionException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	@Override
	public List<CommonTreeNode> getAllResourceTree() throws NoSuchFieldException, SecurityException,
			IllegalArgumentException, IllegalAccessException, InvocationTargetException, IntrospectionException {
		List<SysResource> list = sysResourceRepository.getResourceTree();
		SysResource rootNode = new SysResource();
		rootNode.setResourceId(Constants.RootNode);
		rootNode.setResUniqueId(Constants.RootNode);
		rootNode.setResourceName("菜单列表");
		rootNode.setIconClsId("x-fa fa-th-list");
		rootNode.setSerialNo(1);
		list.add(rootNode);
		// 构建树节点，当提供了排序属性，则构造排序树
		TreeBuilder<SysResource> treeBuilder = new TreeBuilder();
		List<CommonTreeNode> menuList = treeBuilder.build(list, "resUniqueId", "resourceId", "preResourceId",
				"resourceName", "iconClsId", "serialNo", "attachMethod");
		return menuList;
	}

	/**
	 * 更新保存实体 拷贝一个bean中的非空属性于另一个bean中
	 */
	@Override
	public SysResource saveEntity(SysResource entity) {
		SysResource sysResource = sysResourceRepository.getOne(entity.getResUniqueId());
		entity.setResourceName(entity.getResourceNick());
		if (null != sysResource) {
			try {
				// 拷贝一个bean中的非空属性于另一个bean中
				BeanUtil.copyNotNullProperties(sysResource, entity);
				sysResourceRepository.save(sysResource);
			} catch (IllegalAccessException | InvocationTargetException e) {
				log.error(e.getMessage());
			}
		}
		return sysResource;
	}

	/*
	 * (non-Javadoc)
	 */
	/**
	 * 获得每个页面的按钮
	 */
	@Override
	public String getResourceButton(SysUser sysUser, String preResourceId) {
		List<UserRole> userRoles = userRoleRepository.findBySysUser(sysUser);
		List<SysRole> sysRoles = new ArrayList<SysRole>();
		userRoles.forEach(action->{sysRoles.add(sysRoleRepository.findById(action.getSysRole().getRoleId()).get());});
		List<ResourceRole> resourceRoles = new ArrayList<>();
		sysRoles.forEach(action->resourceRoles.addAll(resourceRoleRepository.findBySysRole(action)));
		List<String> ids = new ArrayList<>();
		resourceRoles.forEach(action->ids.add(action.getSysResource().getResUniqueId()));
		List<SysResource> sysResources = sysResourceRepository.findByResUniqueIdIn(ids);
		List<SysResource> list = sysResources.stream().map(mapper->mapper).distinct().filter(predicate->predicate.getResourceType().equals(ResourceType.Button.getIntValue())).collect(Collectors.toList());
		List<SysResource> pagelist = sysResourceRepository.findByResourceTypeAndStateAndPreResourceIdOrderBySerialNoAsc(
				ResourceType.Button.getIntValue(), YesNo.Yes.getIntValue(), preResourceId);
		pagelist.retainAll(list);
		StringBuffer buff = new StringBuffer("[");
		for (SysResource sysResource : pagelist) {
			buff.append("{id:'" + sysResource.getResourceId() + "',name:'" + sysResource.getResourceNick() + "',icon:'"
					+ sysResource.getIconClsId() + "',tooltip:'" + sysResource.getToolTip() + "',method:'"
					+ sysResource.getAttachMethod() + "',color:'" + sysResource.getButtonClr() + "'},");
		}
		if(pagelist.isEmpty()) {
			return "[]";
		}
		if (list.size() > 0) {
			return buff.substring(0, buff.length() - 1) + "]";
		}
		return "[]";
	}

	/*
	 * (non-Javadoc)
	 */
	/**
	 * 删除资源
	 */
	@Transactional
	@Override
	public ResultMsg deleteResources(String resUniqueId) {
		SysResource sysResource = this.get(resUniqueId);
		if (null == sysResource) {
			return new ResultMsg(false, "未找到该资源，可能该资源已被删除");
		}
		List<SysResource> resources = sysResourceRepository.findByResourceIdStartingWith(sysResource.getResourceId());
		List<String> ids = resources.stream().map(mapper -> mapper.getResUniqueId()).collect(Collectors.toList());
		resourceRoleRepository.deleteByResUniqueIds(ids);
		sysResourceRepository.deleteByResUniqueIdIn(ids);
		return new ResultMsg(true, "删除成功");

	}


	@Override
	public SysResource getByResourceId(String resourceId) {
		// TODO Auto-generated method stub
		return sysResourceRepository.findByResourceId(resourceId);
	}


	@Override
	public String getContextMenu(SysUser sysUser, String preResourceId,boolean isView) {
		// TODO Auto-generated method stub
		List<SysRole> sysRoles = sysUser.getSysRoles();
		List<SysResource> list = new ArrayList<SysResource>();
		int type = 0;
		if(isView) {
			type = ResourceType.ViewMenu.getIntValue();
		}else {
			type = ResourceType.Other.getIntValue();
		}
		for (SysRole sysRole : sysRoles) {
			//根据角色获取菜单
			List<ResourceRole> resourceRole = resourceRoleRepository.findBySysRole(sysRole);
			List<SysResource> sysResources = resourceRole.stream().map(ResourceRole::getSysResource).collect(Collectors.toList());
			for (SysResource sysResource : sysResources) {
				if (!list.contains(sysResource) && sysResource.getResourceType() == type
						&& preResourceId.equals(sysResource.getPreResourceId())) {
					list.add(sysResource);
				}
			}
		}
//		List<SysResource> sysList = new ArrayList<SysResource>();
//		sysList.addAll(list);
//		//判断子集菜单是否分配
//		for (SysResource sysResource : list) {
//			List<SysResource> childernList = sysResourceRepository.findByPreResourceIdAndResourceType(sysResource.getResourceId(),type);
//			for (SysResource sysResource2 : childernList) {
//				List<ResourceRole> resourceRoles = resourceRoleRepository.findBySysResourceAndSysRole(sysResource2,sysRoles.get(0));
//				if(resourceRoles.size()>0) {
//					sysList.add(sysResource2);
//				}
//			}
//		}
		Collections.sort(list, new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2) {
				SysResource stu1 = (SysResource) o1;
				SysResource stu2 = (SysResource) o2;
				if (stu1.getSerialNo() > stu2.getSerialNo()) {
					return 1;
				} else if (stu1.getSerialNo() == stu2.getSerialNo()) {
					return 0;
				} else {
					return -1;
				}
			}
		});
		StringBuffer buff = new StringBuffer("[");
		for (SysResource sysResource : list) {
			List<SysResource> resourceList = sysResourceRepository.findByPreResourceIdAndResourceType(sysResource.getResourceId(),sysResource.getResourceType());
			StringBuffer child = new StringBuffer("[");
			String childString = "[]";
			if(resourceList.size()>0) {
				for(SysResource resource : resourceList) {
					if(resourceRoleRepository.findBySysResourceAndSysRole(resource,sysRoles.get(0)).size()>0) {
						child.append("{id:'" + resource.getResourceId() + "',name:'" + resource.getResourceNick() + "',icon:'"
								+ resource.getIconClsId() + "',tooltip:'" + resource.getToolTip() + "',method:'"
								+ resource.getAttachMethod() + "',color:'"
								+ resource.getButtonClr() + "'},");
						childString = child.substring(0, child.length() - 1) + "]";
					}

				}
				
			}
			buff.append("{id:'" + sysResource.getResourceId() + "',name:'" + sysResource.getResourceNick() + "',icon:'"
					+ sysResource.getIconClsId() + "',tooltip:'" + sysResource.getToolTip() + "',method:'"
					+ sysResource.getAttachMethod() + "',color:'"
					+ sysResource.getButtonClr() + "',children:"+childString+"},");
			
		}
		if (list.size() > 0) {
			return buff.substring(0, buff.length() - 1) + "]";
		}
		return "[]";
	}

}